package backed.service.impl;

import backed.entity.EcoBehavior;
import backed.entity.User;
import backed.repository.BehaviorRepository;
import backed.repository.UserRepository;
import backed.service.BehaviorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Service
public class BehaviorServicelmpl implements BehaviorService {
    @Autowired
    private BehaviorRepository behaviorRepository;
    @Autowired
    private UserRepository userRepository;

    @Override
    public EcoBehavior record(Long userId, String behaviorType, Long value) {
        EcoBehavior behavior = new EcoBehavior();
        behavior.setUserId(userId);
        behavior.setValue(BigDecimal.valueOf(value));
        behavior.setRecordDate(java.time.LocalDate.now());
        behavior.setBehaviorType(behaviorType);


        boolean isSupported = behaviorType.equals(EcoBehavior.TYPE_WALK) || 
                             behaviorType.equals(EcoBehavior.TYPE_BIKE) || 
                             behaviorType.equals(EcoBehavior.TYPE_RECYCLE) || 
                             behaviorType.equals(EcoBehavior.TYPE_SAVE_WATER) || 
                             behaviorType.equals(EcoBehavior.TYPE_SAVE_ELECTRICITY);
        
        if (!isSupported) {
            System.out.println("不支持的行为类型。当前支持：walk, bike, recycle, save_water, save_electricity。");
            throw new IllegalArgumentException("不支持的行为类型：" + behaviorType);
        }

        calculateCarbonMetrics(behavior);
        
        // 保存环保行为记录
        EcoBehavior savedBehavior = behaviorRepository.save(behavior);
        
        // 更新用户碳积分
        User user = userRepository.findById(userId)
            .orElseThrow(() -> new RuntimeException("用户不存在: " + userId));
        
        // 获取用户当前碳积分，默认为0
        Integer currentPoints = user.getCarbonPoints() != null ? user.getCarbonPoints() : 0;
        // 累加新的碳积分
        user.setCarbonPoints(currentPoints + savedBehavior.getCarbonPoints());
        // 保存更新后的用户信息
        userRepository.save(user);
        
        return savedBehavior;
    }



    /**
     * 根据环保行为类型和数值计算减碳量和碳积分
     */
    private void calculateCarbonMetrics(EcoBehavior behavior) {
        String behaviorType = behavior.getBehaviorType();
        BigDecimal value = behavior.getValue();
        
        BigDecimal carbonReduction = BigDecimal.ZERO;
        Integer carbonPoints = 0;
        
        // 根据不同行为类型使用不同的计算系数
        switch (behaviorType) {
            case EcoBehavior.TYPE_WALK:
                // 假设每1000步减少0.2kg碳排放，获得2个积分
                carbonReduction = value.divide(BigDecimal.valueOf(1000), 2, BigDecimal.ROUND_HALF_UP)
                                      .multiply(BigDecimal.valueOf(0.2));
                carbonPoints = value.divide(BigDecimal.valueOf(1000))
                                   .multiply(BigDecimal.valueOf(2)).intValue();
                break;
            case EcoBehavior.TYPE_BIKE:
                // 假设每骑行1公里减少0.3kg碳排放，获得3个积分
                carbonReduction = value.multiply(BigDecimal.valueOf(0.3));
                carbonPoints = value.multiply(BigDecimal.valueOf(3)).intValue();
                break;
            case EcoBehavior.TYPE_RECYCLE:
                // 假设每回收1kg物品减少0.8kg碳排放，获得8个积分
                carbonReduction = value.multiply(BigDecimal.valueOf(0.8));
                carbonPoints = value.multiply(BigDecimal.valueOf(8)).intValue();
                break;
            case EcoBehavior.TYPE_SAVE_WATER:
                // 假设每节约1升水减少0.0003kg碳排放，获得0.01个积分
                carbonReduction = value.multiply(BigDecimal.valueOf(0.0003));
                carbonPoints = value.multiply(BigDecimal.valueOf(1)).intValue();
                break;
            case EcoBehavior.TYPE_SAVE_ELECTRICITY:
                // 假设每节约1度电减少0.6kg碳排放，获得6个积分
                carbonReduction = value.multiply(BigDecimal.valueOf(0.6));
                carbonPoints = value.multiply(BigDecimal.valueOf(6)).intValue();
                break;
        }
        
        behavior.setCarbonReduction(carbonReduction);
        behavior.setCarbonPoints(carbonPoints);
    }
    
    @Override
    public Map<String, Object> getStatistics(Long userId) {
        Map<String, Object> stats = new HashMap<>();
        
        // 获取用户所有环保行为记录
        List<EcoBehavior> behaviors = behaviorRepository.findAllByUserId(userId);
        
        // 如果没有找到记录，使用空列表进行后续操作
        if (behaviors == null) {
            behaviors = List.of();
        }
        
        // 计算总减碳量
        BigDecimal totalReduction = BigDecimal.ZERO;
        // 计算总积分
        int totalPoints = 0;
        // 按行为类型统计减碳量
        Map<String, BigDecimal> behaviorStats = new HashMap<>();
        
        for (EcoBehavior behavior : behaviors) {
            // 计算总减碳量
            BigDecimal carbonReduction = behavior.getCarbonReduction();
            if (carbonReduction != null) {
                totalReduction = totalReduction.add(carbonReduction);
            }
            
            // 计算总积分
            Integer carbonPoints = behavior.getCarbonPoints();
            if (carbonPoints != null) {
                totalPoints += carbonPoints;
            }
            
            // 按行为类型统计减碳量
            String behaviorType = behavior.getBehaviorType();
            BigDecimal typeReduction = behaviorStats.getOrDefault(behaviorType, BigDecimal.ZERO);
            if (carbonReduction != null) {
                typeReduction = typeReduction.add(carbonReduction);
            }
            behaviorStats.put(behaviorType, typeReduction);
        }
        
        // 设置返回数据
        stats.put("totalCarbonReduction", totalReduction);
        stats.put("totalCarbonPoints", totalPoints);
        stats.put("behaviorStats", behaviorStats);
        
        return stats;
    }

    @Override
    public List<Map<String, Object>> trend(long userId, LocalDate startDate, LocalDate endDate) {
        // 获取指定日期范围内的用户环保行为记录
        List<EcoBehavior> behaviors = behaviorRepository.findByUserIdAndRecordDateBetween(userId, startDate, endDate);
        
        if (behaviors == null) {
            behaviors = List.of();
        }
        
        // 按日期分组
        Map<LocalDate, List<EcoBehavior>> dateBehaviorMap = new HashMap<>();
        for (EcoBehavior behavior : behaviors) {
            LocalDate date = behavior.getRecordDate();
            List<EcoBehavior> dateBehaviors = dateBehaviorMap.getOrDefault(date, new ArrayList<>());
            dateBehaviors.add(behavior);
            dateBehaviorMap.put(date, dateBehaviors);
        }
        
        // 统计每天的碳减排量和积分
        List<Map<String, Object>> resultList = new ArrayList<>();
        for (Map.Entry<LocalDate, List<EcoBehavior>> entry : dateBehaviorMap.entrySet()) {
            Map<String, Object> dailyStats = new HashMap<>();
            List<EcoBehavior> behaviorList = entry.getValue();
            
            // 计算当天总碳减排量
            BigDecimal dailyReduction = BigDecimal.ZERO;
            // 计算当天总积分
            int dailyPoints = 0;
            
            for (EcoBehavior behavior : behaviorList) {
                BigDecimal carbonReduction = behavior.getCarbonReduction();
                if (carbonReduction != null) {
                    dailyReduction = dailyReduction.add(carbonReduction);
                }
                
                Integer carbonPoints = behavior.getCarbonPoints();
                if (carbonPoints != null) {
                    dailyPoints += carbonPoints;
                }
            }
            
            // 获取日期字符串
            String date = entry.getKey().toString();
            
            dailyStats.put("date", date);
            dailyStats.put("carbonReduction", dailyReduction);
            dailyStats.put("carbonPoints", dailyPoints);
            
            resultList.add(dailyStats);
        }
        
        // 按日期排序
        resultList.sort((a, b) -> a.get("date").toString().compareTo(b.get("date").toString()));
        
        return resultList;
    }
    
    @Override
    public List<Map<String, Object>> getRanking(String type, int limit) {
        LocalDate now = LocalDate.now();
        LocalDate startDate = null;
        
        // 根据类型确定日期范围
        switch (type) {
            case "daily":
                startDate = now;
                break;
            case "weekly":
                // 本周第一天（周一）
                startDate = now.minusDays(now.getDayOfWeek().getValue() - 1);
                break;
            case "monthly":
                // 本月第一天
                startDate = now.withDayOfMonth(1);
                break;
            case "all":
            default:
                // 所有时间
                startDate = LocalDate.of(2020, 1, 1); // 设置一个较早的日期
                break;
        }
        
        // 获取日期范围内的所有环保行为记录
        List<EcoBehavior> behaviors = behaviorRepository.findAllByRecordDateBetween(startDate, now);
        
        if (behaviors == null || behaviors.isEmpty()) {
            return List.of();
        }
        
        // 按用户分组，统计每个用户的总积分
        Map<Long, Integer> userPointsMap = new HashMap<>();
        for (EcoBehavior behavior : behaviors) {
            Long userId = behavior.getUserId();
            Integer carbonPoints = behavior.getCarbonPoints();
            if (carbonPoints != null) {
                userPointsMap.put(userId, userPointsMap.getOrDefault(userId, 0) + carbonPoints);
            }
        }
        
        // 转换为排行榜数据
        List<Map<String, Object>> rankingList = new ArrayList<>();
        for (Map.Entry<Long, Integer> entry : userPointsMap.entrySet()) {
            Map<String, Object> rankingInfo = new HashMap<>();
            rankingInfo.put("userId", entry.getKey());
            rankingInfo.put("carbonPoints", entry.getValue());
            // 这里需要用户信息，暂时留空，后续可以通过用户服务获取
            rankingInfo.put("nickname", "用户" + entry.getKey());
            rankingList.add(rankingInfo);
        }
        
        // 按积分降序排序
        rankingList.sort((a, b) -> Integer.compare(
            (int) b.get("carbonPoints"),
            (int) a.get("carbonPoints")
        ));
        
        // 限制返回数量
        if (rankingList.size() > limit) {
            rankingList = rankingList.subList(0, limit);
        }
        
        return rankingList;
    }


}
